package com.yjy.quartz.job;

import com.yjy.quartz.constant.QuartzConstant;
import org.quartz.*;
import org.quartz.impl.JobDetailImpl;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 实现序列化接口、防止重启应用出现quartz Couldn't retrieve job because a required class was not found 的问题
 * Job 的实例要到该执行它们的时候才会实例化出来。每次 Job 被执行，一个新的 Job 实例会被创建。
 * 其中暗含的意思就是你的 Job 不必担心线程安全性，因为同一时刻仅有一个线程去执行给定 Job 类的实例，甚至是并发执行同一 Job 也是如此。
 *
 * @DisallowConcurrentExecution 保证上一个任务执行完后，再去执行下一个任务，这里的任务是同一个任务
 */
@DisallowConcurrentExecution // Job中的任务有可能并发执行，例如任务的执行时间过长，而每次触发的时间间隔太短，则会导致任务会被并发执行。如果是并发执行，就需要一个数据库锁去避免一个数据被多次处理。
public class JobExecutor implements Job, Serializable {

    private static final long serialVersionUID = 1L;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDetailImpl jobDetail = (JobDetailImpl) context.getJobDetail();
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        try {
            if (!SpringContextUtil.containsBean(jobDetail.getName())) {
                SpringContextUtil.setBean(jobDetail.getName(), jobDetail.getJobDataMap().getString(QuartzConstant.JOB_EXECUTOR));
            }
            Executor executor = (Executor) SpringContextUtil.getBean(jobDetail.getName());

            Map<String, String> paramContext = (Map<String, String>) jobDataMap.get(QuartzConstant.JOB_PARAMS);
            executor.execute(paramContext);
            System.out.printf("时间：%s, 线程：%s, 执行jobName：%s 完成\n", LocalDateTime.now(), Thread.currentThread().getName(), jobDetail.getName());
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("方法出错，添加错误日志"); // TODO 错误时做告警功能
        }
    }
}